class MovieClip extends egret.DisplayObjectContainer
{
    private delegate: MovieClipDelegate;
    /**
     * 动画的播放帧频
     * @member {number} egret.MovieClip#frameRate
     */
    public frameRate: number = 60;
    constructor(data,texture?: egret.Texture)
    {
        super();
        if(data instanceof DefaultMovieClipDelegate)
        {
            egret.Logger.warning("MovieClip#constructor接口参数已经变更，请尽快调整用法为 new MovieClip(data,texture)")
            this.delegate = data;
        }
        else
        {
            this.delegate = new DefaultMovieClipDelegate(data,texture);
        }
        this.delegate.setMovieClip(this);
    }

    /**
     * 播放指定动画
     * @method egret.MovieClip#gotoAndPlay
     * @param frameName {string} 指定帧的帧名称
 
     */
    public gotoAndPlay(frameName: string)
    {
        this.delegate.gotoAndPlay(frameName);
    }

    /**
     * 播放并暂停指定动画
     * @method egret.MovieClip#gotoAndStop
     * @param frameName {string} 指定帧的帧名称
 
     */
    public gotoAndStop(frameName: string)
    {
        this.delegate.gotoAndStop(frameName);
    }


    /**
     * 暂停动画
     * @method egret.MovieClip#stop
     */
    public stop()
    {
        this.delegate.stop();
    }

    /**
     * @method egret.MovieClip#dispose
     */
    public dispose(): void
    {
        this.delegate.dispose();
    }

    /**
     * 方法名改为 dispose
     * @method egret.MovieClip#release
     * @deprecated
     */
    public release()
    {
        egret.Logger.warning("MovieClip#release方法即将废弃");
        this.dispose();
    }


    /**
     * @method egret.MovieClip#getCurrentFrameIndex
     * @deprecated
     * @returns {number}
     */
    public getCurrentFrameIndex(): number
    {
        egret.Logger.warning("MovieClip#getCurrentFrameIndex方法即将废弃");
        return this.delegate["_currentFrameIndex"];
    }

    /**
     * 获取当前影片剪辑的帧频数
     * @method egret.MovieClip#getTotalFrame
     * @deprecated
     * @returns {number}
     */
    public getTotalFrame(): number
    {
        egret.Logger.warning("MovieClip#getTotalFrame方法即将废弃");
        return this.delegate["_totalFrame"];
    }

    /**
     * @method egret.MovieClip#setInterval
     * @deprecated
     * @param value {number}
     */
    public setInterval(value: number)
    {
        egret.Logger.warning("MovieClip#setInterval方法即将废弃,请使用MovieClip#frameRate代替");
        this.frameRate = 60 / value;
    }

    /**
     * @method egret.MovieClip#getIsPlaying
     * @deprecated
     * @returns {boolean}
     */
    public getIsPlaying(): boolean
    {
        egret.Logger.warning("MovieClip#getIsPlaying方法即将废弃");
        return this.delegate["isPlaying"];
    }
}

interface MovieClipDelegate
{
    gotoAndPlay(frameName: string): void;
    gotoAndStop(frameName: string): void;
    stop(): void;
    dispose(): void;
    setMovieClip(movieclip: MovieClip): void;
}

class DefaultMovieClipDelegate implements MovieClipDelegate
{
    private _frameData;
    private _totalFrame: number = 0;
    private _spriteSheet: egret.SpriteSheet;
    private _passTime: number = 0;
    private _currentFrameIndex: number = 0;
    private _currentFrameName: string;
    private _isPlaying: boolean = false;
    private movieClip: MovieClip;
    private bitmap: egret.Bitmap;
    constructor(public data,texture: egret.Texture)
    {
        this._frameData = data;
        this._spriteSheet = new egret.SpriteSheet(texture);
    }
    public setMovieClip(movieClip: MovieClip): void
    {
        this.movieClip = movieClip;
        this.bitmap = new egret.Bitmap();
        this.movieClip.addChild(this.bitmap);

    }
    public gotoAndPlay(frameName: string): void
    {
        this.checkHasFrame(frameName);
        this._isPlaying = true;
        this._currentFrameIndex = 0;
        this._currentFrameName = frameName;
        this._totalFrame = this._frameData.frames[frameName].totalFrame;
        this.playNextFrame();
        this._passTime = 0;
        egret.Ticker.getInstance().register(this.update,this);
    }
    public gotoAndStop(frameName: string): void
    {
        this.checkHasFrame(frameName);
        this.stop();
        this._passTime = 0;
        this._currentFrameIndex = 0;
        this._currentFrameName = frameName;
        this._totalFrame = this._frameData.frames[frameName].totalFrame;
        this.playNextFrame();
    }
    public stop(): void
    {
        this._isPlaying = false;
        egret.Ticker.getInstance().unregister(this.update,this);
    }
    public dispose(): void
    {
    }
    private checkHasFrame(name: string)
    {
        if(this._frameData.frames[name] == undefined)
        {
            egret.Logger.fatal("MovieClip没有对应的frame：",name);
        }
    }
    private update(advancedTime: number): void
    {
        var oneFrameTime = 1000 / this.movieClip.frameRate;
        var last = this._passTime % oneFrameTime;
        var num = Math.floor((last + advancedTime) / oneFrameTime);
        while(num >= 1)
        {
            if(num == 1)
            {
                this.playNextFrame();
            }
            else
            {
                this.playNextFrame(false);
            }
            num--;
        }
        this._passTime += advancedTime;
    }
    private playNextFrame(needShow: boolean = true)
    {
        var frameData = this._frameData.frames[this._currentFrameName].childrenFrame[this._currentFrameIndex];
        if(needShow)
        {
            var texture: egret.Texture = this.getTexture(frameData.res);
            var bitmap = this.bitmap;
            bitmap.x = frameData.x;
            bitmap.y = frameData.y;
            bitmap.texture = texture;
        }
        if(frameData.action != null)
        {
            this.movieClip.dispatchEventWith(frameData.action);
        }
        this._currentFrameIndex++;
        if(this._currentFrameIndex == this._totalFrame)
        {
            this._currentFrameIndex = 0;
            if(frameData.action != egret.Event.COMPLETE)
            {
                this.movieClip.dispatchEventWith(egret.Event.COMPLETE);
            }
        }
    }
    private getTexture(name: string): egret.Texture
    {
        var resData = this._frameData.res[name];
        var texture = this._spriteSheet.getTexture(name);
        if(!texture)
        {
            texture = this._spriteSheet.createTexture(name,resData.x,resData.y,resData.w,resData.h);
        }
        return texture;
    }
}